/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package be.hogent.iii.project.connectie;

import be.hogent.iii.project.objects.Spel;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;

/**
 *
 * @author Dieter Van der Stock
 */
public class Connectie implements Runnable {

    private static final int POORT = 5678;
    
    SocketChannel clientKanaal;
    ByteBuffer buffer;
    private static Selector selector;
    
    public Connectie(String ip) {
        try {
            //clientSocketKanaal aanmaken en configureren
            //clientKanaal = SocketChannel.open();
            clientKanaal = SocketChannel.open(new InetSocketAddress(ip, POORT));
            clientKanaal.configureBlocking(false);
            //clientKanaal.connect(new InetSocketAddress(HOSTADRES, POORT));
            
            //buffer voor het antwoord van de server in te lezen aanmaken
            buffer = ByteBuffer.allocate(1048);
            
            //we hebben allemaal een beetje bevestiging nodig in het leven...
            System.out.println("Connectie met server " + ip + " op poort " + Integer.toString(POORT) + " succesvol aangemaakt.");
            
            
            //connectionClient.register(selector, SelectionKey.OP_CONNECT);
        }
        catch (IOException ioEx) {
            System.out.println("Connectie met server " + ip + " op poort " + Integer.toString(POORT) + " kon NIET worden aangemaakt.");
            System.out.println("Zonder server kunnen we niet veel doen. Programma wordt beëindigd.");
            System.out.println(ioEx.getMessage());
            System.exit(1);
        }
    }
    
    public void run() {
        System.out.println("Luisterthread gestart, nu gaan we wachten op een bericht van de server...");
        while(true) {
            wachtOpAntwoord();
        }
    }
    
    /**
     * Stuurt een tekstbericht naar de server en geeft het antwoord terug.
     * 
     * @param bericht De tekst die we willen sturen.
     * @return Het antwoord van de server, leeg als we niets kregen of er een timeout was
     */
    public void stuurTekstBericht(String bericht) {
        String antwoord = "";
        
        try {
            //voor testmogelijkheden:
            System.out.println("We sturen door: " + bericht);

            //ons bericht in den buffer steken
            byte[] berichtInBytes = bericht.getBytes();
            buffer.put(berichtInBytes);
            
            //buffer omdraaien voor we heb doorsturen
            buffer.flip();
            
            //ons selector-object creeëren om straks te kunnen wachten op het antwoord
            selector = Selector.open();

            //ons clientKanaal registreren bij de selector voor het ontvangen van binnenkomende data
            clientKanaal.register(selector, SelectionKey.OP_READ);
            
            //ons bericht doorsturen
            clientKanaal.write(buffer);
        } 
        catch (IOException ioEx) {
            System.out.println("\nFout met selector, register of clientKanaal read/write.");
            System.out.println(ioEx.getMessage());
        }     
        catch (NullPointerException npEx) {
            System.out.println("\nProbleem in stuurTekstBericht. Mogelijk is de server niet online.");
            System.out.println(npEx.getMessage());
        }
        /*catch (Exception ex) {
            System.out.println("Een onbekende fout trad op in stuurTekstBericht");
            System.out.println(ex.getMessage());
        }*/
    }
    
    public void wachtOpAntwoord() {
        String antwoord = "";
        SelectionKey aanvraag = null;
        
        try {
            
            //maximum 500 milliseconden wachten op antwoord, anders timeout
            //while (selector.select(500) > 0) {
            while (selector.select() > 0) {
                //System.out.println("In de while");
                
                //de events die zijn voorgekomen opvragen
                Set aanvragenSet = selector.selectedKeys();
                
                System.out.println("In de select, de keys (als er zijn) werden eruit gehaald");

                //een iterator aanmaken om door de set te navigeren
                Iterator aanvragenIt = aanvragenSet.iterator();

                //alle aanvragen aflopen (niet echt nodig want er is maar één mogelijkheid ma alle...)
                while (aanvragenIt.hasNext()) {
                    System.out.println("Aanvraag binnengekregen, we proberen te lezen.");
                    aanvraag = (SelectionKey) aanvragenIt.next();

                    //huidige aanvraag verwijderen zodat we die niet meer tegenkomen
                    //aanvragenSet.remove(aanvraag);
                    //aanvragenIt.remove();

                    //als we kunnen lezen van ons kanaal, doen we dat ook..
                    if (aanvraag.isReadable()) {

                        //buffer leegmaken eer we er iets nieuws insteken
                        buffer.clear();

                        //lezen wat de server heeft teruggestuurd
                        int aantalBytes = clientKanaal.read(buffer);

                        //als we bytes binnenkregen maken we er een string van
                        if (aantalBytes != 0) {
                            int aantalChars = buffer.position();
                            byte[] bufferArray = buffer.array();
                            antwoord = new String(bufferArray, 0, aantalChars);
                        }
                        System.out.println("Antwoord: " + antwoord);
                    }
                    selector.selectedKeys().remove(aanvraag);
                }
                //wacht();
            }
        } 
        catch (IOException ioEx) {
            System.out.println("\nFout met selector, register of clientKanaal read/write in wachtOpAntwoord.");
            System.out.println(ioEx.getMessage());
        }     
        catch (NullPointerException npEx) {
            System.out.println("\nProbleem in wachtOpAntwoord. Mogelijk is de server niet online.");
            System.out.println(npEx.getMessage());
        }
        catch (Exception ex) {
            System.out.println("Een onbekende fout trad op in wachtOpAntwoord");
            System.out.println(ex.getMessage());
        }
        
    }
    
    public void sluitConnectie() {
        try {
            System.out.println("Connectie wordt gesloten...");
            clientKanaal.close();
        } 
        catch (IOException ioEx) {
            System.out.println("Disconnecten gefaald.");
            System.out.println(ioEx.getMessage());
        }
        catch (NullPointerException npEx) {
            System.out.println("\nProbleem met het afsluiten van de socket. Mogelijk is de server niet online.");
            System.out.println(npEx.getMessage());
        }
    }
    
    /**
     * Stuurt het complete spel in zijn huidige status door naar een client dmv serialisatie
     * 
     * @param spel Het complete spel dat naar de client wordt gestuurd.
     * @return Het antwoord van de server: is de map goed aangekomen? Leeg indien er een fout voorkwam.
     */
    public String stuurSpel(Spel spel) {
        String antwoord = "";
        
        //we roepen de lidfunctie van Spel aan die zichzelf zal serialiseren tot een bestand, en het pad
        //waar dat bestand staat teruggeeft
        String filenaam = spel.serialiseer();
        
        //er we deze data in een XML bestand kunnen doorsturen, moeten we eerst de bytes van het file
        //omzetten naar een string, gebruik makend van Base64 codering.
         try {
             String spelData = Base64.zetOm(filenaam);
        } catch(IOException ioEx) {
            System.out.println("Fout voorgekomen in getBytesFromFile");
            ioEx.printStackTrace();
        } 
        return antwoord;
    }
    
    private void wacht() {
        try {
            //System.out.println("Wacht");
        Thread.currentThread().sleep(500);
        
        }
        catch (Exception ex) {
            ex.printStackTrace();
        }
    }
}

